from python_jichu.public import print_1

print_1('类')


class Person:
    # 私有属性只能通过类的方法访问
    __adb = 'asdf'

    def __init__(self, name, age, sex):
        """
        构造函数它在创建对象时自动调用，用于初始化对象的属性。
        :param name:
        :param age:
        :param sex:
        """
        self.name = name
        self.age = age
        self.sex = sex

    @classmethod
    def class_methods(cls):
        """
        类方法的第一个参数是 cls，而不是 self，它可以访问类的属性和方法。
        :return:
        """
        pass

    @staticmethod
    def static_method():
        """
        静态方法不依赖实例（对象），可以通过类直接调用。
        :return:
        """
        pass


p = Person('name', 'age', 'sex')
print(p.name)
print(p.age)
print(p.sex)

print_1('类的继承')
class Student(Person):
    """
    类的继承
    """
    def __init__(self, name, age, sex, student_id):
        super().__init__(name, age, sex)  # 调用父类的构造方法
        self.student_id = student_id

    def greet(self):
        print(f"Hello, my name is {self.name}, I am {self.age} years old, and my student ID is {self.student_id}.")

print_1('魔法方法（特殊方法）')
class Point:
    """
    Python 类有许多“魔法方法”，它们通常以 __ 开头和结尾，允许我们定制类的行为。

    __str__(self)：当你打印对象时会调用此方法，返回一个字符串表示。
    __repr__(self)：通常用于调试时，返回对象的“官方”字符串表示。
    __add__(self, other)：定义加法运算符的行为。
    """
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return f"Point({self.x}, {self.y})"

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)


p1 = Point(1, 2)
p2 = Point(3, 4)
print(p1)  # 调用 __str__
p3 = p1 + p2  # 调用 __add__
print(p3)


print_1('类属性,和对象属性')
class MyClass:
    """
    类属性是类的状态修改后,每个实例都是修改后的,会影响后面的实例的值
    对象属性是实例化后的属性,只在这个实例中,其他的实例不受影响
    """
    count = 0  # 类属性

    def __init__(self):
        MyClass.count += 1

    @classmethod
    def get_count(cls):
        return cls.count
a = MyClass()
a.count = 10  # 这里修改的是实例属性中的count 类属性不变
MyClass.count = 5  # 这里修改的是属性方法, 由于类中没又定义实例方法所以下面打印的时候用的类方法值给属性方法赋值输出
b = MyClass()
print(b.count, a.count)
b.count = 12  # 这里改的还是属性方法
print(b.count)
print(MyClass.count)
print(b.get_count())  # 实例可以调用类属性,但是最好是用类调用类属性


print_1('单例实例')
class Singleton:
    _instance = None

    def __new__(cls):
        """
        __new__ 方法负责创建类的实例，而 __init__ 方法负责初始化类的实例。
        换句话说，__new__ 是一个负责实例化对象的构造方法，它在 __init__ 之前被调用。
        """
        if cls._instance is None:
            # 创建Singleton实例并且赋值给类属性, 二次在实例化的时候因为类属性中有实例化的对象,所以不在实例新的对象,而是上次的对象
            cls._instance = super(Singleton, cls).__new__(cls)
        return cls._instance

    @classmethod
    def get_instance(cls):
        print('--')
        return cls._instance

# 获取单例实例
obj1 = Singleton()
obj2 = Singleton()

print(obj1 is obj2)


